#include <iostream>
#include <string>
#include <memory>

// -------------------- Image 接口 --------------------

class Image {
public:
    virtual void display() = 0;      // 显示图像的方法
    virtual ~Image() {}
};

// -------------------- RealImage 类 --------------------

// 真实的图像类，负责实际的图像加载和显示
class RealImage : public Image {
private:
    std::string filename;

    // 私有方法，模拟从磁盘加载图像
    void loadFromDisk() {
        std::cout << "Loading " << filename << " from disk.\n";
    }

public:
    // 构造函数，初始化文件名并加载图像
    RealImage(const std::string& fname) : filename(fname) {
        loadFromDisk();
    }

    // 实现 display 方法，显示图像
    void display() override {
        std::cout << "Displaying " << filename << ".\n";
    }

    // 析构函数
    ~RealImage() {
        std::cout << "Destroying RealImage: " << filename << "\n";
    }
};

// -------------------- ProxyImage 类 --------------------

// 代理图像类，控制对 RealImage 的访问
class ProxyImage : public Image {
private:
    std::string filename;
    RealImage* realImage; // 指向真实图像的指针

public:
    // 构造函数，初始化文件名，暂时不加载图像
    ProxyImage(const std::string& fname) : filename(fname), realImage(nullptr) {}

    // 实现 display 方法，延迟加载真实图像
    void display() override {
        if (!realImage) {
            std::cout << "ProxyImage: RealImage not loaded yet. Loading now...\n";
            realImage = new RealImage(filename);
        } else {
            std::cout << "ProxyImage: RealImage already loaded. Displaying now...\n";
        }
        realImage->display();
    }

    // 析构函数，释放 RealImage 内存
    ~ProxyImage() {
        delete realImage;
        std::cout << "Destroying ProxyImage: " << filename << "\n";
    }
};

// -------------------- 测试用例 --------------------

int main() {
    // 使用代理创建图像对象
    Image* image1 = new ProxyImage("test_image1.jpg");
    Image* image2 = new ProxyImage("test_image2.png");

    std::cout << "----- Displaying image1 for the first time -----\n";
    image1->display(); // 第一次显示，应该加载并显示图像

    std::cout << "\n----- Displaying image1 for the second time -----\n";
    image1->display(); // 第二次显示，应该直接显示而不重新加载

    std::cout << "\n----- Displaying image2 for the first time -----\n";
    image2->display(); // 显示另一个图像，应该加载并显示

    // 释放内存
    delete image1;
    delete image2;

    return 0;
}
